import { IElementTheme } from "./IElementTheme.js";
import { GetAliasSet } from "./IUtil.js";

export class IElementView extends IElementTheme {
    constructor() {
        super();

        // 元素基本属性
        this.m_tagname = "Element";
        this.m_attributes = {}; // 属性集合

        // 元素关系
        this.m_window = null; // 所属窗口
        this.m_root = null; // 根元素
        this.m_position_ancestor = null;  // 定位祖先元素
        this.m_position_descendants = []; // 定位元素列表
        this.m_parent = null; // 父元素
        this.m_childrens = []; // 子元素列表

        // 元素状态变化标志
        this.m_children_changed = false;
        this.m_attribute_changed = false;
        this.m_style_changed = false;
        this.m_layout_changed = true;
        this.m_position_changed = true;

        // 视口
        this.m_viewport_x = 0;
        this.m_viewport_y = 0;
        this.m_viewport_width = 0;
        this.m_viewport_height = 0;
        // 内容视口
        this.m_content_viewport_x = 0;
        this.m_content_viewport_y = 0;
        this.m_content_viewport_width = 0;
        this.m_content_viewport_height = 0;
        // 大小和位置
        this.m_x = 0;
        this.m_y = 0;
        this.m_width = 0;
        this.m_height = 0;
        // 内部填充和外边距
        this.m_padding_left = 0;
        this.m_padding_top = 0;
        this.m_padding_right = 0;
        this.m_padding_bottom = 0;
        this.m_margin_left = 0;
        this.m_margin_top = 0;
        this.m_margin_right = 0;
        this.m_margin_bottom = 0;
        // 边框
        this.m_border_left_width = 0;
        this.m_border_top_width = 0;
        this.m_border_right_width = 0;
        this.m_border_bottom_width = 0;
        this.m_border_left_color = 'black';
        this.m_border_top_color = 'black';
        this.m_border_right_color = 'black';
        this.m_border_bottom_color = 'black';
        // 圆角
        this.m_border_radius = 0;
        // 滚动位置
        this.m_scroll_x = 0;
        this.m_scroll_y = 0;
    }

    // 元素基本属性
    SetTagName(tagname) { this.m_tagname = tagname; }
    GetTagName() { return this.m_tagname; }
    GetAttributes() { return this.m_attributes; }
    SetVisible(visible) { this.m_visible = visible; }
    IsVisible() { return this.m_visible; }
    SetDisabled(disabled) { this.m_disabled = disabled; }
    IsDisabled() { return this.m_disabled; }
    SetReadOnly(readonly) { this.m_readonly = readonly; }
    IsReadOnly() { return this.m_readonly; }
    SetFocus(focus) { this.m_focus = focus; }
    IsFocus() { return this.m_focus; }
    SetHover(hover) { this.m_hover = hover; }
    IsHover() { return this.m_hover; }
    SetAttached(attached) { this.m_attached = attached; }
    IsAttached() { return this.m_attached; }
    SetDraggable(draggable) { this.m_draggable = draggable; }
    IsDraggable() { return this.m_draggable; }
    SetDroppable(droppable) { this.m_droppable = droppable; }
    IsDroppable() { return this.m_droppable; }
    SetDragging(dragging) { this.m_dragging = dragging; }
    IsDragging() { return this.m_dragging; }

    // 元素关系
    SetWindow(window) { this.m_window = window; }
    GetWindow() { return this.m_window; }
    GetWindowWidth() { return this.m_window ? this.m_window.GetWindowWidth() : 0; }
    GetWindowHeight() { return this.m_window ? this.m_window.GetWindowHeight() : 0; }
    SetRoot(root) { this.m_root = root; }
    GetRoot() { return this.m_root; }
    GetPositionAncestor() { return this.m_position_ancestor; }
    GetPositionDescendants() { return this.m_position_descendants; }
    SetParent(parent) { this.m_parent = parent; }
    GetParent() { return this.m_parent; }
    GetChildrens() { return this.m_childrens; }

    // 元素状态变化标志
    SetChildrenChanged(changed) { this.m_children_changed = changed; }
    SetAttributeChanged(changed) { this.m_attribute_changed = changed; }
    SetStyleChanged(changed) { this.m_style_changed = changed; }
    SetLayoutChanged(changed) { this.m_layout_changed = changed; }
    SetPositionChanged(changed) { this.m_position_changed = changed; }
    IsChildrenChanged() { return this.m_children_changed; }
    IsAttributeChanged() { return this.m_attribute_changed; }
    IsStyleChanged() { return this.m_style_changed; }
    IsLayoutChanged() { return this.m_layout_changed; }
    IsPositionChanged() { return this.m_position_changed; }

    // 视口
    SetViewPortX(x) { this.m_viewport_x = x; }
    SetViewPortY(y) { this.m_viewport_y = y; }
    SetViewPortWidth(width) { this.m_viewport_width = width; }
    SetViewPortHeight(height) { this.m_viewport_height = height; }
    GetViewPortX() { return this.m_viewport_x; }
    GetViewPortY() { return this.m_viewport_y; }
    GetViewPortWidth() { return this.m_viewport_width; }
    GetViewPortHeight() { return this.m_viewport_height; }
    // 内容视口
    SetContentViewPortX(x) { this.m_content_viewport_x = x; }
    SetContentViewPortY(y) { this.m_content_viewport_y = y; }
    SetContentViewPortWidth(width) { this.m_content_viewport_width = width; }
    SetContentViewPortHeight(height) { this.m_content_viewport_height = height; }
    GetContentViewPortX() { return this.m_content_viewport_x; }
    GetContentViewPortY() { return this.m_content_viewport_y; }
    GetContentViewPortWidth() { return this.m_content_viewport_width; }
    GetContentViewPortHeight() { return this.m_content_viewport_height; }
    // 大小和位置
    SetX(x) { this.m_x = x; }
    SetY(y) { this.m_y = y; }
    SetWidth(width) { this.m_width = width; }
    SetHeight(height) { this.m_height = height; }
    GetX() { return this.m_x; }
    GetY() { return this.m_y; }
    GetWidth() { return this.m_width; }
    GetHeight() { return this.m_height; }
    // 边框 填充 边距 圆角
    GetBorderLeftWidth() { return this.m_border_left_width; }
    GetBorderTopWidth() { return this.m_border_top_width; }
    GetBorderRightWidth() { return this.m_border_right_width; }
    GetBorderBottomWidth() { return this.m_border_bottom_width; }
    SetBorderLeftWidth(width) { this.m_border_left_width = width; }
    SetBorderTopWidth(width) { this.m_border_top_width = width; }
    SetBorderRightWidth(width) { this.m_border_right_width = width; }
    SetBorderBottomWidth(width) { this.m_border_bottom_width = width; }
    GetBorderLeftColor() { return this.m_border_left_color; }
    GetBorderTopColor() { return this.m_border_top_color; }
    GetBorderRightColor() { return this.m_border_right_color; }
    GetBorderBottomColor() { return this.m_border_bottom_color; }
    SetBorderLeftColor(color) { this.m_border_left_color = color; }
    SetBorderTopColor(color) { this.m_border_top_color = color; }
    SetBorderRightColor(color) { this.m_border_right_color = color; }
    SetBorderBottomColor(color) { this.m_border_bottom_color = color; }
    SetPaddingLeft(padding) { this.m_padding_left = padding; }
    SetPaddingTop(padding) { this.m_padding_top = padding; }
    SetPaddingRight(padding) { this.m_padding_right = padding; }
    SetPaddingBottom(padding) { this.m_padding_bottom = padding; }
    GetPaddingLeft() { return this.m_padding_left; }
    GetPaddingTop() { return this.m_padding_top; }
    GetPaddingRight() { return this.m_padding_right; }
    GetPaddingBottom() { return this.m_padding_bottom; }
    SetMarginLeft(margin) { this.m_margin_left = margin; }
    SetMarginTop(margin) { this.m_margin_top = margin; }
    SetMarginRight(margin) { this.m_margin_right = margin; }
    SetMarginBottom(margin) { this.m_margin_bottom = margin; }
    GetMarginLeft() { return this.m_margin_left; }
    GetMarginTop() { return this.m_margin_top; }
    GetMarginRight() { return this.m_margin_right; }
    GetMarginBottom() { return this.m_margin_bottom; }
    SetBorderRadius(radius) { this.m_border_radius = radius; }
    GetBorderRadius() { return this.m_border_radius; }
    // 滚动位置
    GetScrollX() { return this.m_scroll_x; }
    GetScrollY() { return this.m_scroll_y; }
    SetScrollX(x) { this.m_scroll_x = x; }
    SetScrollY(y) { this.m_scroll_y = y; }

    // 边框
    SetBorder(width, style, color) {
        if (!color) {
            color = color || style;
            style = "solid";
        }
        width = width < 0 ? 0 : width;
        this.m_border_top_width = width;
        this.m_border_top_color = color;
        this.m_border_right_width = width;
        this.m_border_right_color = color;
        this.m_border_bottom_width = width;
        this.m_border_bottom_color = color;
        this.m_border_left_width = width;
        this.m_border_left_color = color;
    }

    SetBorderWidth(width) {
        this.m_border_top_width = width;
        this.m_border_right_width = width;
        this.m_border_bottom_width = width;
        this.m_border_left_width = width;
    }

    SetBorderStyle(style) {
        this.m_border_top_style = style;
        this.m_border_right_style = style;
        this.m_border_bottom_style = style;
        this.m_border_left_style = style;
    }

    // 填充 top_right_bottom_left  top_bottom_left_right  top_right_bottom_left_right
    SetPadding(padding_top, padding_right, padding_bottom, padding_left) {
        padding_right = padding_right || padding_top;
        padding_bottom = padding_bottom || padding_top;
        padding_left = padding_left || padding_right;
        this.m_padding_top = padding_top < 0 ? 0 : padding_top;
        this.m_padding_right = padding_right < 0 ? 0 : padding_right;
        this.m_padding_bottom = padding_bottom < 0 ? 0 : padding_bottom;
        this.m_padding_left = padding_left < 0 ? 0 : padding_left;
    }

    // 间距 top_right_bottom_left  top_bottom_left_right  top_right_bottom_left_right
    SetMargin(margin_top, margin_right, margin_bottom, margin_left) {
        margin_right = margin_right || margin_top;
        margin_bottom = margin_bottom || margin_top;
        margin_left = margin_left || margin_right;
        this.m_margin_top = margin_top < 0 ? 0 : margin_top;
        this.m_margin_right = margin_right < 0 ? 0 : margin_right;
        this.m_margin_bottom = margin_bottom < 0 ? 0 : margin_bottom;
        this.m_margin_left = margin_left < 0 ? 0 : margin_left;
    }

    // 设置定位元素相对那个父元素进行定位
    SetPositionAncestor(position_ancestor) {
        if (this.m_position_ancestor == position_ancestor) {
            return;
        }
        // 从旧定位祖先元素中删除
        if (this.m_position_ancestor) {
            const index = this.m_position_ancestor.m_position_descendants.indexOf(this);
            if (index !== -1) {
                this.m_position_ancestor.m_position_descendants.splice(index, 1);
            }
        }
        this.m_position_ancestor = position_ancestor;
        // 添加到新定位祖先元素中
        if (this.m_position_ancestor) {
            this.m_position_ancestor.m_position_descendants.push(this);
        }
    }

    // 判断元素是否是某个元素的祖先元素
    IsAncestor(element) {
        let cur_el = this;
        while (cur_el && cur_el !== element) {
            cur_el = cur_el.GetParent();
        }

        return cur_el === element && element;
    }

    // 插入子元素
    InsertChildren(target_children, anchor_children = null) {
        if (this.m_childrens.includes(target_children) || !target_children || target_children === this) {
            return false;
        }
        if (anchor_children === null) {
            this.m_childrens.push(target_children);
        } else {
            const index = this.m_childrens.indexOf(anchor_children);
            if (index !== -1) {
                this.m_childrens.splice(index, 0, target_children);
            } else {
                this.m_childrens.push(target_children);
            }
        }
        target_children.SetParent(this);
        if (this.IsAttached() && target_children.OnAttached) {
            target_children.OnAttached();
        }
        if (!this.IsChildrenChanged()) {
            this.SetChildrenChanged(true);
            this.SetLayoutChanged(true);
            this.SetLocalWidth(-1);
            this.SetLocalHeight(-1);
            this.Refresh();
        }
        return true;
    }

    // 删除子元素
    DeleteChildren(target_children) {
        const childrens = this.GetChildrens();
        const index = childrens.indexOf(target_children);
        if (index === -1) {
            return false;
        }
        childrens.splice(index, 1);
        target_children.SetParent(null);
        if (this.IsAttached() && target_children.OnDetached) {
            target_children.OnDetached();
        }
        if (!this.IsChildrenChanged()) {
            this.SetChildrenChanged(true);
            this.SetLayoutChanged(true);
            this.SetLocalWidth(-1);
            this.SetLocalHeight(-1);
            this.Refresh();
        }
        return true;
    }

    // 删除所有子元素
    ClearChildren() {
        this.m_childrens = [];
        this.SetChildrenChanged(true);
    }

    OnAttached() {
        const parent = this.GetParent();
        this.SetAttached(true);
        this.SetRoot(parent.GetRoot() || parent.GetRoot());
        this.SetWindow(parent.GetWindow() || parent.GetWindow());
        const childrens = this.GetChildrens();
        childrens.forEach((children) => {
            children.OnAttached();
        });
    }

    // 插入子属性
    InsertAttribute(key, value) {
        if (this.m_attributes[key] === value) {
            return false;
        }
        this.m_attribute_changed = true;
        this.m_attributes[key] = value;
        this.Refresh();
        return true;
    }

    // 删除子属性
    DeleteAttribute(key) {
        if (this.m_attributes[key] === undefined) {
            return false;
        }
        this.m_attributes[key] = undefined;
        this.m_attribute_changed = true;
        this.Refresh();
        return true;
    }

    // 设置属性的setter和getter
    SetAttributeSetterGetter(key, setter, getter) {
        const keys = GetAliasSet(key);
        const attributes = this.GetAttributes();
        const raw_key = "__" + key + "__";
        keys.forEach((key) => {
            Object.defineProperty(attributes, key, {
                set: (value) => {
                    attributes[raw_key] = value;
                    if (setter) {
                        setter(value);
                    }
                },
                get: () => {
                    if (getter) {
                        return getter();
                    }
                    return attributes[raw_key];
                },
                configurable: true,
            });
        });
    }

    GetBooleanAttributeValue(attribute_key, default_attribute_value) {
        const attribute_value = this.m_attributes[attribute_key];
        if (attribute_value === undefined) {
            return default_attribute_value;
        } else {
            return attribute_value === "true" || attribute_value === true || attribute_value === "" || attribute_value === "yes" || attribute_value === "on";
        }
    }

    GetIntegerAttributeValue(attribute_key, default_attribute_value) {
        const attribute_value = this.m_attributes[attribute_key];
        return parseInt(attribute_value === undefined ? default_attribute_value : attribute_value);
    }

    GetNumberAttributeValue(attribute_key, default_attribute_value) {
        const attribute_value = this.m_attributes[attribute_key];
        return parseFloat(attribute_value === undefined ? default_attribute_value : attribute_value);
    }

    GetStringAttributeValue(attribute_key, default_attribute_value) {
        const attribute_value = this.m_attributes[attribute_key];
        return attribute_value === undefined ? default_attribute_value : attribute_value;
    }

    IsExistAttributeValue(attribute_key) {
        return this.m_attributes[attribute_key] !== undefined;
    }

    UpdateChildren() {
        this.SetChildrenChanged(false);
    }

    UpdateAttribute() {
        this.SetAttributeChanged(false);
    }

    UpdateStyle() {
        this.SetStyleChanged(false);
    }

    UpdateLayout() {
        this.SetLayoutChanged(false);
    }

    UpdatePosition() {
        this.SetPositionChanged(false);
    }

    // 渲染元素
    Render(painter) {
        if (this.IsChildrenChanged()) this.UpdateChildren();
        if (this.IsAttributeChanged()) this.UpdateAttribute();
        if (this.IsStyleChanged()) this.UpdateStyle();
        if (this.IsLayoutChanged()) this.UpdateLayout();
        if (this.IsPositionChanged()) this.UpdatePosition();

        if (this.m_viewport_width <= 0 || this.m_viewport_height <= 0 || !this.m_visible) return;
        painter.Save();
        painter.Clip(this.m_viewport_x, this.m_viewport_y, this.m_viewport_width, this.m_viewport_height);
        this.OnRenderBackground(painter);
        this.OnRenderBorder(painter);
        this.OnRenderContent(painter);
        this.OnRenderChildren(painter);
        painter.Restore();
        this.OnRenderDescendants(painter);
    }

    // 渲染背景
    OnRenderBackground(painter) {
        if (!this.m_background_color || this.m_background_color === "none") return;

        if (this.m_border_radius && this.m_border_radius > 0) {
            painter.FillRoundRectangle(this.m_x, this.m_y, this.m_width, this.m_height, this.m_border_radius, this.m_background_color);
        } else {
            painter.FillRectangle(this.m_x, this.m_y, this.m_width, this.m_height, this.m_background_color);
        }
    }

    // 渲染边框
    OnRenderBorder(painter) {
        if (this.m_border_left_width && this.m_border_left_width > 0) {
            painter.FillRectangle(this.m_x, this.m_y, this.m_border_left_width, this.m_height, this.m_border_left_color);
        }
        if (this.m_border_top_width && this.m_border_top_width > 0) {
            painter.FillRectangle(this.m_x, this.m_y, this.m_width, this.m_border_top_width, this.m_border_top_color);
        }
        if (this.m_border_right_width && this.m_border_right_width > 0) {
            painter.FillRectangle(this.m_x + this.m_width - this.m_border_right_width, this.m_y, this.m_border_right_width, this.m_height, this.m_border_right_color);
        }
        if (this.m_border_bottom_width && this.m_border_bottom_width > 0) {
            painter.FillRectangle(this.m_x, this.m_y + this.m_height - this.m_border_bottom_width, this.m_width, this.m_border_bottom_width, this.m_border_bottom_color);
        }
    }

    // 渲染内容
    OnRenderContent(painter) {
    }

    // 渲染子元素
    OnRenderChildren(painter) {
        for (const children of this.m_childrens) {
            if (!children.IsVisible() || children.IsDragging() || children.GetPositionAncestor()) continue;
            children.Render(painter);
        }
    }

    OnRenderDescendants(painter) {
        const descendants = this.m_position_descendants;
        for (const descendant of descendants) {
            if (!descendant.IsVisible() || descendant.IsDragging()) continue;
            descendant.Render(painter);
        }
    }
}